package fra;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 分数
 * @author Administrator
 *
 */
public class Fra {
	int sign;//符号位 [-1,0,1]
	BigInteger integer;//整数部分
	BigInteger numerator;//分子
	BigInteger denominator;//分母
	public static final Long MaxCValue=999999999l;//最大计算值
	
	/**构造函数**************************************************/
	public Fra() {
		set();
	}
	public Fra(long l){
		set(l);
	}
	public Fra(long l1,long l2){
		set(l1,l2);
	}
	public Fra(BigInteger l1,BigInteger l2){
		set(l1,l2);
	}
	public Fra(double d){
		set(d);
	}
	public Fra(double d1,double d2){
		set(d1,d2);
	}
	public Fra(Fra fra){
		set(fra);
	}
	/**重写函数**************************************************/
	@Override
	public String toString() {
		StringBuilder sb=new StringBuilder();
		if(getSign()==0)sb.append("0");
		else{
			if(getSign()<0)	sb.append("-");
			if(getInteger().signum()>0){
				sb.append("(");sb.append(getInteger());sb.append(")");
			}
			if(getNumerator().signum()>0){
				sb.append(getNumerator());
				if(getDenominator().compareTo(new BigInteger("1"))>0){sb.append("/");sb.append(getDenominator());}
			}
		}		
		return sb.toString();
	}
	@Override
	public boolean equals(Object obj) {
		if(obj==null)return false;
		if( !(obj instanceof Fra))return false;
		Fra fra=(Fra)obj;
		fra.proper_fraction();
		this.proper_fraction();
		if(getSign()==fra.getSign()&&getNumerator()==fra.getNumerator()&&getDenominator()==fra.getDenominator()){
			return true;
		}
		return false;
	}
	/**检测函数**************************************************/
	public boolean overflow(){
		if(getInteger().signum()<0||getNumerator().signum()<0||getDenominator().signum()<0
				)return true;
		return false;
	}
	public void check(){
		if(denominator.signum()==0){
			throw new ArithmeticException("分母不能为0");
		}
		if(overflow()){
			throw new OutOfMemoryError("数值溢出");
		}
	}
	
	/**功能**************************************************/
	
	/**
	 * 真分数
	 */
	public Fra proper_fraction(){
		if(this.integer==null)this.integer=new BigInteger("0");
		this.numerator=this.numerator.add(this.denominator.multiply(this.integer));
		this.integer=new BigInteger("0");
		return this;
	}
	
	/**
	 * 假分数
	 * @return
	 */
	public Fra improper_fraction(){
		this.integer=this.numerator.divide(this.denominator);
		this.numerator=this.numerator.mod(this.denominator);
		return this;		
	}
	/**
	 * 克隆分数
	 */
	public Fra clone(){
		Fra fra=new Fra();
		fra.numerator=this.numerator;
		fra.denominator=this.denominator;
		fra.integer=this.integer;
		fra.sign=this.sign;
		return fra;
	}
	/**
	 * 获取小数
	 * @return
	 */
	public BigDecimal get(int decimal){
		proper_fraction();
		
		BigInteger n=this.getNumerator();
		if(getSign()<0)
			n=this.getNumerator().multiply(new BigInteger("-1"));
		BigDecimal denominator=new BigDecimal(this.getDenominator());
		BigDecimal numerator=new BigDecimal(n);
		return numerator.divide(denominator, decimal, BigDecimal.ROUND_HALF_UP);
	}
	public BigDecimal get(){
		return get(4);
	}
	/**
	 * 相反数
	 * @return
	 */
	public Fra opposite_number(){
		this.sign=-this.sign;
		return this;
	}
	/**
	 * 倒数
	 * @return
	 */
	public Fra reciprocal(){
		if(getSign()==0){
			throw new ArithmeticException("分母不能为0");
		}
		BigInteger bi=getNumerator();
		setNumerator(getDenominator());
		setDenominator(bi);
		return this;
	}
	/**
	 * 绝对值
	 * @return
	 */
	public Fra absolute_value(){
		if(this.sign!=0)this.sign=1;
		return this;
	}
	public String toString(int d){
		return get(d).toString();
	}
	/**关于Fra分数的运算************************************************/
	/**
	 * 加法
	 * @param f2
	 * @return
	 */
	public Fra plus(Fra f2){
		if(getSign()==0){
			set(f2);
			return this;
		}
		if(f2.getSign()==0)return this;
		int sign=getSign()*f2.getSign();
		if(sign<0){
			if(getSign()<0){
				M.swap(this, f2);
			}
			return minis(f2.opposite_number());	
		}
		try {
			proper_fraction();
			f2.proper_fraction();
			
			BigInteger l1=getNumerator().multiply(f2.getDenominator()).add(getDenominator().multiply(f2.getNumerator()));
			BigInteger l2=getDenominator().multiply(f2.getDenominator());
			
			set(l1,l2);
			return this;
		} catch (OutOfMemoryError e) {
			throw new OutOfMemoryError("数值溢出");
		}
	}
	/**
	 * 减法
	 * @param f1
	 * @param f2
	 * @return
	 */
	public Fra minis(Fra f2){
		if(getSign()==0){
			set(f2);
			opposite_number();
			return this;
		}
		if(f2.getSign()==0)return this;
		int sign=getSign()*f2.getSign();
		if(sign<0){
			return plus(f2.opposite_number());
		}
		if(equals(f2)){
			set(0);
			return this;
		}
		try {
			proper_fraction();
			f2.proper_fraction();
			BigInteger l1=getNumerator().multiply(f2.getDenominator()).abs();
			BigInteger l2=getDenominator().multiply(f2.getNumerator()).abs();
			BigInteger l3=getDenominator().multiply(f2.getDenominator()).abs();
			if(l1.subtract(l2).signum()>0){
				sign=getSign();
				l1=l1.subtract(l2);
			}else{
				sign=-f2.getSign();
				l1=l2.subtract(l1);
			}			
			set(l1,l3);
			this.sign=sign;
			return this;
		} catch (OutOfMemoryError e) {
			throw new OutOfMemoryError("数值溢出");
		}
	}
	/**
	 * 乘法运算
	 * @return
	 */
	public Fra multiplication(Fra f2){
		if(getSign()==0||f2.getSign()==0){
			set(0);
			return this;
		}
		try {
			int sign=getSign()*f2.getSign();
			proper_fraction();
			f2.proper_fraction();
			
			BigInteger l1=getNumerator().multiply(f2.getNumerator());
			BigInteger l2=getDenominator().multiply(f2.getDenominator());
			
			set(l1,l2);
			this.sign=sign;
			
			return this;
		} catch (OutOfMemoryError e) {
			throw new OutOfMemoryError("数值溢出");
		}
	}
	/**
	 * 除法
	 * @param f1
	 * @param f2
	 * @return
	 */
	public Fra division(Fra f2){
		if(getSign()==0){
			set(0);
			return this;
		}
		if(f2.getSign()==0){
			throw new ArithmeticException("被除数不能为0");
		}
		if(equals(f2)){
			set(1);
			return this;
		}
		if(equals(M.opposite_number(f2))){
			set(-1);
			return this;
		}
		try {
			Fra f=f2.clone().reciprocal();
			return multiplication(f);
		} catch (OutOfMemoryError e) {
			throw new OutOfMemoryError("数值溢出");
		}
	}
	/**静态功能**************************************************/
	public static Fra ParseFra(String str){
		if(str==null||str.trim().length()==0){
			throw new NumberFormatException("字符串为空");
		}
		
		String regex="^([(][0-9]*[.]{0,1}[0-9]*[)]){0,1}[0-9]*[.]{0,1}[0-9]*[/]{0,1}[0-9]*[.]{0,1}[0-9]*$";
		
		String regex2="([0-9]*[.]{0,1}[0-9]*)";
		if(!str.matches(regex)){
			throw new NumberFormatException("不符合规范:"+str);
		}
		
		Pattern p = Pattern.compile(regex2);
		Matcher m=p.matcher(str);
		List<String> li_str=new ArrayList<>();
		while(m.find()){
			String s=m.group();
			if(s.trim().length()!=0){
				li_str.add(s=="."?"0":s);
			}
		}
		try {
			if(li_str.size()==1){
				return new Fra(Double.parseDouble(li_str.get(0)));
			}else if(li_str.size()==2){
				return new Fra(Double.parseDouble(li_str.get(0)),Double.parseDouble(li_str.get(1)));
			}else{
				double d1=Double.parseDouble(li_str.get(0));
				double d2=Double.parseDouble(li_str.get(1));
				double d3=Double.parseDouble(li_str.get(2));
				return new Fra(d1*d3+d2,d3);
			}
		} catch (Exception e) {
			throw new RuntimeException("转换时出错，可能是数据太大而溢出");
		}
	}
	/**属性**************************************************/
	private void set(){
		denominator=new BigInteger("1");
		numerator=new BigInteger("0");
		integer=new BigInteger("0");
		sign=0;
	}
	public void set(Fra fra){
		this.integer=fra.integer;
		this.denominator=fra.denominator;
		this.numerator=fra.numerator;
		this.sign=fra.sign;
	}
	public void set(long l1,long l2){
		set();
		if(l2==0){
			throw new ArithmeticException("分母不能为0");
		}
		if(l1==0){
			setNumerator(l1);
			return;
		}
		long l=M.GCD(Math.abs(l1),Math.abs(l2));
		setNumerator(l1/l);
		setDenominator(l2/l);
	}
	public void set(BigInteger l1,BigInteger l2){
		set();
		if(l2.signum()==0){
			throw new ArithmeticException("分母不能为0");
		}
		if(l1.signum()==0){
			setNumerator(0l);
			return;
		}
		BigInteger l=M.GCD(l1.abs(),l2.abs());
		setNumerator(l1.divide(l));
		setDenominator(l2.divide(l));
	}
	public void set(long l){
		set();
		setNumerator(l);
	}
	public void set(double d){
		if(d==0){
			set();
			return;
		}
		set((long)(d*1E+16), (long)1E+16);
	}
	public void set(double d1,double d2){
		if(d2==0){
			throw new ArithmeticException("分母不能为0");
		}
		if(d1==0)return;
		set((long)(d1*1E+16), (long)(d2*1E+16));		
	}
	/*set方法*/
	private void setSign(int sign) {
		if(this.sign==0)this.sign=sign;
		else this.sign *= sign;
	}
	public void setNumerator(Long numerator) {
		if(numerator==null)return;
		setNumerator(new BigInteger(numerator.toString()));
	}
	public void setNumerator(BigInteger numerator) {
		if(numerator==null)return;
		this.numerator =numerator.abs();
		setSign(numerator.signum());
	}
	public void setDenominator(Long denominator) {
		if(denominator==null)return;
		setDenominator(new BigInteger(denominator.toString()));
	}
	public void setDenominator(BigInteger denominator) {
		if(denominator==null)return;
		this.denominator =denominator.abs();
		setSign(denominator.signum());
		check();
	}
	/*get方法*/
	public BigInteger getInteger() {
		return integer;
	}
	public BigInteger getNumerator() {
		return numerator;
	}
	public BigInteger getDenominator() {
		return denominator;
	}
	public int getSign() {
		return sign;
	}
	
	public static void main(String[] args) {
		System.out.println(new Fra(-1));
	}
}
